/********************************************************************************
 * Copyright (c)2016-2020, ShenZhen WanJiaAn Technology CO.,LTD.
 * All Rights Reserved.
 *
 * File Name     : hal_video.c
 * Author        : joki.zhu
 * Date          : 2019-09-23
 *
 * Record        :
 * 1.Date        : 2019-09-23
 *   Author      : joki.zhu
 *   Modification: Created file
 ********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "venc_wrapper.h"
//#include "hi_recorder_pro.h"
//#include "rtsp_wrapper.h"
#include "hi_mw_media_intf.h"
#include "app_common.h"
#include "hi_comm_venc.h"
#include "hi_comm_vpss.h"
#include "hi_comm_isp.h"

#if 0
#include "hi_rtsp_server.h"
#include "rtsp_wrapper.h"
#endif
const HI_U32 MAX_THM_SIZE = 50 * 1024;
//extern HI_MW_PTR g_hRecHandle;
//extern HI_MW_PTR s_hRtspServerHandle;
FILE* g_pFile = NULL;
HI_BOOL bWrite = HI_FALSE;
//sensor type define in makefile.
#if defined(SENSOR_OV4689)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 2688, 1512, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 2688, 1512, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {1, 2688, 1512};
static HI_MW_VPortAttr s_stVPort4MainAttr = {1, 2560, 1440, 30},
                       s_stVPort4SlaveAttr = {2, 640, 360, 30},
                       s_stVPort4ThmAttr = {3, 320, 240, 30};
static HI_MW_VEncAttr s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 2560, 1440, 2764800, 0, 1, 0, HI_FALSE, 20480, 30, 30},
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 172800, 0, 1, 0, HI_FALSE, 2048, 30, 30},
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
#elif defined(SENSOR_MN34120)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 3840, 2160, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 3840, 2160, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {1, 3840, 2160};
static HI_MW_VPortAttr s_stVPort4MainAttr = {0, 3840, 2160, 30},
                       s_stVPort4SlaveAttr = {1, 640, 360, 30},
                       s_stVPort4ThmAttr = {2, 640, 360, 30};
static HI_MW_VEncAttr s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 3840, 2160, 3840 * 2160 * 2, 0, 1, 0, HI_FALSE, 40000, 30, 30},
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 0, 1, 0, HI_FALSE, 2000, 30, 30},
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
#elif defined(SENSOR_IMX477)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 3840, 2160, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 3840, 2160, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {0, 3840, 2160};
static HI_MW_VPortAttr s_stVPort4MainAttr = {0, 3840, 2160, 30},
                       s_stVPort4SlaveAttr = {1, 640, 360, 30},
                       s_stVPort4ThmAttr = {2, 640, 360, 30};
static HI_MW_VEncAttr s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 3840, 2160, 3840 * 2160 * 2, 0, 1, 0, HI_TRUE, 40000, 30, 30},
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 1, 1, 0, HI_TRUE, 2000, 30, 30},
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
#elif defined(SENSOR_IMX117)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 3840, 2160, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 3840, 2160, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {1, 3840, 2160};
static HI_MW_VPortAttr s_stVPort4MainAttr = {0, 3840, 2160, 30},
                       s_stVPort4SlaveAttr = {1, 640, 360, 30},
                       s_stVPort4ThmAttr = {2, 640, 360, 30};
static HI_MW_VEncAttr s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 3840, 2160, 3840 * 2160 * 2, 0, 1, 0, HI_FALSE, 40000, 30, 30},
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 0, 1, 0, HI_FALSE, 2000, 30, 30},
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
#elif defined(SENSOR_OV2718)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 1920, 1080, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 1920, 1080, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {0, 1920, 1080};
static HI_MW_VPortAttr s_stVPort4MainAttr = {0, 1920, 1080, 30},
                       s_stVPort4SlaveAttr = {1, 640, 360, 30},
                       s_stVPort4ThmAttr = {2, 320, 240, 30};
static HI_MW_VEncAttr s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 1920, 1080, 1920 * 1080 * 2, 0, 1, 0, HI_TRUE, 10000, 30, 30},
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 1, 1, 0, HI_TRUE, 2000, 30, 30},
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
#elif defined(SENSOR_IMX307)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 1920, 1080, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 1920, 1080, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {0, 1920, 1080};
static HI_MW_VPortAttr s_stVPort4MainAttr = {0, 1920, 1080, 30},
                       s_stVPort4SlaveAttr = {1, 640, 360, 30},
                       s_stVPort4ThmAttr = {2, 320, 240, 30};
static HI_MW_VEncAttr s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 1920, 1080, 1920 * 1080 * 2, 0, 1, 0, HI_TRUE, 10000, 30, 30},
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 1, 1, 0, HI_TRUE, 2000, 30, 30},
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
#elif defined(SENSOR_PS5260)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 1920, 1080, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 1920, 1080, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {0, 1920, 1080};
static HI_MW_VPortAttr s_stVPort4MainAttr = {0, 1920, 1080, 15},
                       s_stVPort4SlaveAttr = {1, 640, 360, 15},
                       s_stVPort4ThmAttr = {2, 320, 240, 15};
static HI_MW_VEncAttr 
                      //s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 0, 1, 0, HI_TRUE, 180, 15*2, 15},
                      s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 0, 1, 0, HI_TRUE, 160, 15*2, 15},
                      //s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 1920, 1080, 1920 * 1080 * 2, 0, 1, 0, HI_TRUE, 10000, 30, 30},  
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 1, 1, 0, HI_TRUE, 2000, 30, 15},
                      //s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 15};
#elif defined(SENSOR_JXF37)
static HI_MW_SensorAttr_S s_stSensorAttr = {0, 1920, 1080, 30};
static HI_MW_VCapAttr_S s_stVCapAttr = {0, 1920, 1080, 30};
static HI_MW_VProcAttr_S s_stVProcAttr = {0, 1920, 1080};
static HI_MW_VPortAttr s_stVPort4MainAttr = {0, 1920, 1080, 15},
                       s_stVPort4SlaveAttr = {1, 640, 360, 15},
                       s_stVPort4ThmAttr = {2, 320, 240, 15};
static HI_MW_VEncAttr 
                      //s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 0, 1, 0, HI_TRUE, 180, 15*2, 15},
                      s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 0, 1, 0, HI_TRUE, 160, 15*4, 15},
                      //s_stVEnc4MainAttr = {0, HI_MW_PAYLOAD_TYPE_H264, 1920, 1080, 1920 * 1080 * 2, 0, 1, 0, HI_TRUE, 10000, 30, 30},  
                      s_stVEnc4SlaveAttr = {1, HI_MW_PAYLOAD_TYPE_H264, 640, 360, 640 * 360 * 2, 1, 1, 0, HI_TRUE, 2000, 30, 15},
                      //s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 30};
                      s_stVEnc4ThmAttr = {2, HI_MW_PAYLOAD_TYPE_JPEG, 320, 240, 320 * 240 * 2, 0, 1, 0, HI_FALSE, 1000, 30, 15};
#endif

static HI_MW_VideoBindMap_S s_astMediaAttr[] =
{
    {&s_stVProcAttr, &s_stVPort4MainAttr, &s_stVEnc4MainAttr},
    //{&s_stVProcAttr, &s_stVPort4SlaveAttr, &s_stVEnc4SlaveAttr},
    {&s_stVProcAttr, &s_stVPort4ThmAttr, &s_stVEnc4ThmAttr},
};

static HI_U32 s_u32LostPacket = 0;

//extern HI_BOOL IsMainVideoTrackSource(HI_Track_Source_S* pstTrackSource);

//static OnDataReceived_FN s_pfnOnThmReceiveCB = NULL;
static HI_U8* s_pu8ThmData = NULL;

HI_S32 SAMPLE_COMM_SaveStreamFile(HI_HANDLE VencHdl, HI_MW_MEDIA_VIDEO_S* pVStreamData, HI_VOID* pPrivateData)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_CHAR aFileName[128] = {0};
    HI_CHAR aPayLoadType[8] = {0};
    FILE* pVencFile = NULL;

    static int total_num = 0;
    if (total_num++ >= 1000) {
        return 0;   
    }
    printf("total_num----------%d\n", total_num);
    
    switch (pVStreamData->astPack[0].stDataType.enPayloadType)
    {
        case HI_MW_PAYLOAD_TYPE_H264:
            snprintf(aPayLoadType, 8, "%s", "h264");
            break;
        case HI_MW_PAYLOAD_TYPE_H265:
            snprintf(aPayLoadType, 8, "%s", "h265");
            break;
        default:
            printf("enPayloadType is error.\n");
            return -1;
    }

    if (pPrivateData != NULL)
    {
        snprintf(aFileName, 128, "/sdcard/%s_chn%d.%s", (char*)pPrivateData, VencHdl, aPayLoadType);
    }
    else
    {
        snprintf(aFileName, 128, "/sdcard/%s_chn%d.%s", "null", VencHdl, aPayLoadType);
    }

    if (pVStreamData->u32Seq == 0)
    {
        pVencFile = fopen(aFileName, "w");
    }
    else
    {
        pVencFile = fopen(aFileName, "a");
    }

    if (pVencFile == NULL)
    {
        printf("fopen %s error.\n", aFileName);
        return HI_FAILURE;
    }

    HI_U32 i = 0;
    HI_U8* pPackVirtAddr;
    HI_U32 u32PackLen;
    HI_U32 u32PackOffset;
    for ( i = 0 ; i < pVStreamData->u32PackCount; i++ )
    {
        pPackVirtAddr = pVStreamData->astPack[i].pu8Addr[0];
        u32PackLen = pVStreamData->astPack[i].au32Len[0];
        u32PackOffset = pVStreamData->astPack[i].u32Offset;
        s32Ret = fwrite(pPackVirtAddr + u32PackOffset, u32PackLen - u32PackOffset, 1, pVencFile);
        printf("[%s] fwrite u64PTS:%lld pPackVirtAddr:%p u32PackLen-u32PackOffset %d\n", __FUNCTION__, pVStreamData->astPack[0].u64PTS, pPackVirtAddr, u32PackLen - u32PackOffset);
        if (s32Ret < 0)
        {
            printf("fwrite error %d\n", s32Ret);
        }
#if  1 //add by joki 处理一个包有多段情况
        if (2 == pVStreamData->astPack[i].u32SegCnt) 
        {
            pPackVirtAddr = pVStreamData->astPack[i].pu8Addr[1];
            u32PackLen = pVStreamData->astPack[i].au32Len[1];
            s32Ret = fwrite(pPackVirtAddr + u32PackOffset, u32PackLen - u32PackOffset, 1, pVencFile);
            printf("[%s] fwrite u64PTS:%lld pPackVirtAddr:%p u32PackLen-u32PackOffset %d\n", __FUNCTION__, pVStreamData->astPack[0].u64PTS, pPackVirtAddr, u32PackLen - u32PackOffset);
            if (s32Ret < 0)
            {
                printf("fwrite error %d\n", s32Ret);
            }            
        }
#endif /* #if 1 */        
        if (fflush(pVencFile))
        {
            perror("fflush file\n");
        }
    }

    if (fclose(pVencFile))
    {
        printf("fclose error\n");
    }
    
    return HI_SUCCESS;
}

static HI_S32 VEncDataProc(__attribute__((unused))HI_HANDLE hVEncHdl, HI_MW_MEDIA_VIDEO_S* pVStreamData, HI_VOID* pPrivateData)
{
#if 0
    HI_Track_Source_Handle pTrackSource = (HI_Track_Source_Handle)pPrivateData;
    HI_REC_FRAME_DATA_S stRecFrame;
    stRecFrame.u32SliceCnt = 0;
    HI_S32 s32Ret;
    HI_U32 i;
    for (i = 0; i < pVStreamData->u32PackCount; i++)
    {
        stRecFrame.apu8SliceAddr[stRecFrame.u32SliceCnt] = pVStreamData->astPack[i].pu8Addr[0] + pVStreamData->astPack[i].u32Offset;
        stRecFrame.au32SliceLen[stRecFrame.u32SliceCnt] = pVStreamData->astPack[i].au32Len[0] - pVStreamData->astPack[i].u32Offset;
        stRecFrame.u32SliceCnt++;
        //retrace happened,only on liteos,one packet devide two segment.
        if (2 == pVStreamData->astPack[i].u32SegCnt)
        {
            stRecFrame.apu8SliceAddr[stRecFrame.u32SliceCnt] = pVStreamData->astPack[i].pu8Addr[1] + pVStreamData->astPack[i].u32Offset;
            stRecFrame.au32SliceLen[stRecFrame.u32SliceCnt] = pVStreamData->astPack[i].au32Len[1] - pVStreamData->astPack[i].u32Offset;
            stRecFrame.u32SliceCnt++;
        }
        stRecFrame.u64TimeStamp = pVStreamData->astPack[i].u64PTS;
        if (HI_MW_PAYLOAD_TYPE_H264 == pVStreamData->astPack[i].stDataType.enPayloadType)
        {
            if (HI_MW_H264E_NALU_ISLICE == pVStreamData->astPack[i].stDataType.enH264EType
                || HI_MW_H264E_NALU_IDRSLICE == pVStreamData->astPack[i].stDataType.enH264EType
                || HI_MW_H264E_NALU_SPS == pVStreamData->astPack[0].stDataType.enH264EType)
            {
                stRecFrame.bKeyFrameFlag = HI_TRUE;
            }
            else
            {
                stRecFrame.bKeyFrameFlag = HI_FALSE;
            }
        }
        else if (HI_MW_PAYLOAD_TYPE_H265 == pVStreamData->astPack[i].stDataType.enPayloadType)
        {
            if (HI_MW_H265E_NALU_ISLICE == pVStreamData->astPack[i].stDataType.enH265EType
                || HI_MW_H265E_NALU_IDRSLICE == pVStreamData->astPack[i].stDataType.enH265EType
                || HI_MW_H265E_NALU_SPS == pVStreamData->astPack[0].stDataType.enH265EType)
            {
                stRecFrame.bKeyFrameFlag = HI_TRUE;
            }
            else
            {
                stRecFrame.bKeyFrameFlag = HI_FALSE;
            }
        }
        else
        {
            stRecFrame.bKeyFrameFlag = HI_FALSE;
        }
    }
    s32Ret = HI_REC_WriteData(g_hRecHandle, pTrackSource, &stRecFrame);
    if (HI_SUCCESS != s32Ret && IsMainVideoTrackSource(pTrackSource))
    {
        s_u32LostPacket++;
    }
    return s32Ret;
#endif
}

HI_S32 HalVideoVencStart(HI_HANDLE hVEncHdl, HI_MW_OnVEncDataCB_FN pfnDataCB)
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

    return HI_MW_VEnc_Start(hVEncHdl, -1, pfnDataCB, NULL);
}

HI_S32 HalVideoVencRequestIDR(HI_HANDLE hVEncHdl)
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

    return HI_MW_VEnc_RequestIDR(hVEncHdl);
}

HI_S32 HalVideoVencStop(HI_HANDLE hVEncHdl, HI_MW_OnVEncDataCB_FN pfnDataCB)
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

    return HI_MW_VEnc_Stop(hVEncHdl, pfnDataCB);
}


HI_S32 HalVideoSetColor2Grey(HI_HANDLE hVEncHdl, HI_BOOL bEnable)
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

    HI_S32 s32Ret = HI_SUCCESS;	
    VENC_CHN_PARAM_S stChnParam;

#if 1
      VI_PIPE ViPipe = 0;
      ISP_PUB_ATTR_S stPubAttr = { 0 };
      ISP_EXPOSURE_ATTR_S stExpAttr = { 0 };
      ISP_DRC_ATTR_S stDRC ={0};
      
#if 0
      s32Ret = HI_MPI_ISP_GetPubAttr(ViPipe, &stPubAttr);
      if (HI_SUCCESS != s32Ret) {
       LOGE("HI_MPI_ISP_GetPubAttr chn:%d failed\n", hVEncHdl);
       return -1;
      }
     
      stPubAttr.f32FrameRate = (bEnable == 1) ? 10 : 15;
      s32Ret = HI_MPI_ISP_SetPubAttr(ViPipe, &stPubAttr);
      if (HI_SUCCESS != s32Ret) {
       LOGE("HI_MPI_ISP_SetPubAttr chn:%d failed\n", hVEncHdl);
       return -1;
      }
#endif
       s32Ret = HI_MPI_ISP_GetExposureAttr(ViPipe, &stExpAttr);
      if (HI_SUCCESS != s32Ret) {
       LOGE("HI_MPI_ISP_GetExposureAttr chn:%d failed\n", hVEncHdl);
       return -1;
      }
      s32Ret = HI_MPI_ISP_GetDRCAttr(ViPipe, &stDRC);
      if (HI_SUCCESS != s32Ret) {
       LOGE("HI_MPI_ISP_GetDRCAttr chn:%d failed\n", hVEncHdl);
       return -1;
      }
      if (HI_SUCCESS != s32Ret) {
       LOGE("HI_MPI_ISP_GetExposureAttr chn:%d failed\n", hVEncHdl);
       return -1;
      }
      if (bEnable) {   stDRC.bEnable = 0;
       //stExpAttr.stAuto.stExpTimeRange.u32Max = 1000000;
       stExpAttr.stAuto.stAGainRange.u32Max = 15360;
       stExpAttr.stAuto.stISPDGainRange.u32Max = 1562;
      } else {
       stDRC.bEnable = 1;
       //stExpAttr.stAuto.stExpTimeRange.u32Max = 666666;
       stExpAttr.stAuto.stAGainRange.u32Max = 15360;
       stExpAttr.stAuto.stISPDGainRange.u32Max = 1562;
      }
     
      s32Ret = HI_MPI_ISP_SetDRCAttr(ViPipe, &stDRC);
      if (HI_SUCCESS != s32Ret) {
       LOGE("HI_MPI_ISP_GetDRCAttr chn:%d failed\n", hVEncHdl);
       return -1;
      }
      s32Ret = HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);
      if (HI_SUCCESS != s32Ret) {
       LOGE("HI_MPI_ISP_SetExposureAttr chn:%d failed\n", hVEncHdl);
       return -1;
      }
#endif

    memset(&stChnParam, 0, sizeof(stChnParam));
    s32Ret = HI_MPI_VENC_GetChnParam(hVEncHdl, &stChnParam);
    if (HI_SUCCESS != s32Ret) {
        LOGE("HI_MPI_VENC_GetChnParam chn:%d failed\n", hVEncHdl);
        return -1;
    }

    stChnParam.bColor2Grey = bEnable;
    s32Ret = HI_MPI_VENC_SetChnParam(hVEncHdl, &stChnParam);
    if (HI_SUCCESS != s32Ret) {
        LOGE("HI_MPI_VENC_SetChnParam chn:%d failed\n", hVEncHdl);
        return -1;
    }

    return s32Ret;
}

HI_S32 HalVideoSetResolution(HI_HANDLE hVEncHdl, HI_MW_VEncAttr *pstVEncAttr)
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

	if (pstVEncAttr == NULL) {
		LOGE("Params is NULL\n");
		return -1;
	}

	HI_S32 s32Ret = HI_SUCCESS;	
	
	memcpy(s_astMediaAttr[hVEncHdl].pstVEncAttr, pstVEncAttr, sizeof(HI_MW_VEncAttr));

 	s32Ret = HI_MW_Media_StopVenc(&s_astMediaAttr[hVEncHdl]);
	if (HI_SUCCESS != s32Ret) {
		LOGE("HI_MW_Media_StopVenc hVEncHdl:%d failed\n", hVEncHdl);
		return -1;
	}	
	
	s32Ret = HI_MW_Media_StartVenc(&s_astMediaAttr[hVEncHdl]);
	if (HI_SUCCESS != s32Ret) {
		LOGE("HI_MW_Media_StartVenc hVEncHdl:%d failed\n", hVEncHdl);
		return -1;
	}	
	
    return s32Ret;
}

HI_S32 HalVideoGetResolution(HI_HANDLE hVEncHdl, HI_MW_VEncAttr *pstVEncAttr)
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

	if (pstVEncAttr == NULL) {
		LOGE("Params is NULL\n");
		return -1;
	}

	HI_S32 s32Ret = HI_SUCCESS;	
    VENC_CHN_ATTR_S stVencAttr;

    memset(&stVencAttr, 0, sizeof(stVencAttr));
	s32Ret = HI_MPI_VENC_GetChnAttr(hVEncHdl, &stVencAttr);
	if (HI_SUCCESS != s32Ret) {
        LOGE("HI_MPI_VENC_GetChnAttr failed with %#x!\n", s32Ret);
        return -1;
	}
    
	pstVEncAttr->WIDTH = stVencAttr.stVencAttr.u32PicWidth;
    pstVEncAttr->HEIGHT = stVencAttr.stVencAttr.u32PicHeight;

    switch (stVencAttr.stRcAttr.enRcMode)
    {
        case VENC_RC_MODE_H264CBR:
            pstVEncAttr->GOP = stVencAttr.stRcAttr.stH264Cbr.u32Gop;
            pstVEncAttr->FRAMERATE = stVencAttr.stRcAttr.stH264Cbr.fr32DstFrameRate;
            break;
        case VENC_RC_MODE_H264VBR:
            pstVEncAttr->GOP = stVencAttr.stRcAttr.stH264Vbr.u32Gop;
            pstVEncAttr->FRAMERATE = stVencAttr.stRcAttr.stH264Vbr.fr32DstFrameRate;
            break;
        case VENC_RC_MODE_H264AVBR: /* Not support for Hi3556AV100/Hi3556V200/Hi3559V200 */
            pstVEncAttr->GOP = stVencAttr.stRcAttr.stH264AVbr.u32Gop;
            pstVEncAttr->FRAMERATE = stVencAttr.stRcAttr.stH264AVbr.fr32DstFrameRate;
            break;
        case VENC_RC_MODE_H264QVBR:
            pstVEncAttr->GOP = stVencAttr.stRcAttr.stH264QVbr.u32Gop;
            pstVEncAttr->FRAMERATE = stVencAttr.stRcAttr.stH264QVbr.fr32DstFrameRate;
            break;
        case VENC_RC_MODE_H264CVBR:
            pstVEncAttr->GOP = stVencAttr.stRcAttr.stH264CVbr.u32Gop;
            pstVEncAttr->FRAMERATE = stVencAttr.stRcAttr.stH264CVbr.fr32DstFrameRate;
            break;
        case VENC_RC_MODE_H264FIXQP:
            pstVEncAttr->GOP = stVencAttr.stRcAttr.stH264FixQp.u32Gop;
            pstVEncAttr->FRAMERATE = stVencAttr.stRcAttr.stH264FixQp.fr32DstFrameRate;
            break;
        case VENC_RC_MODE_H264QPMAP: /* Not support for Hi3556AV100/Hi3556V200/Hi3559V200 */
            pstVEncAttr->GOP = stVencAttr.stRcAttr.stH264QpMap.u32Gop;
            pstVEncAttr->FRAMERATE = stVencAttr.stRcAttr.stH264QpMap.fr32DstFrameRate;
            break;
    }
	
    return s32Ret;
}

static HI_S32 copy_jpg_data(unsigned char *pDataBuf, int dataMaxSize, int *pOutSize, VENC_STREAM_BUF_INFO_S *pstStreamBuf, VENC_STREAM_S* pstStream)
{
    HI_U32 i,j;
    HI_U64 u64SrcPhyAddr;
    HI_U32 u32Left;
    HI_S32 s32Ret = 0;
    int offset = 0;
    int copySize = 0;
    int remainBufSize = dataMaxSize;

    for(i = 0; i< pstStream->u32PackCount; i++)
    {
        for(j=0; j<MAX_TILE_NUM; j++)
        {
            if((pstStream->pstPack[i].u64PhyAddr > pstStreamBuf->u64PhyAddr[j])&&\
                (pstStream->pstPack[i].u64PhyAddr <= pstStreamBuf->u64PhyAddr[j]+pstStreamBuf->u64BufSize[j]))
                break;
        }

        if(pstStream->pstPack[i].u64PhyAddr + pstStream->pstPack[i].u32Len >=
                pstStreamBuf->u64PhyAddr[j] + pstStreamBuf->u64BufSize[j])
        {
            if (pstStream->pstPack[i].u64PhyAddr + pstStream->pstPack[i].u32Offset >=
                pstStreamBuf->u64PhyAddr[j] + pstStreamBuf->u64BufSize[j])
            {
                /* physical address retrace in offset segment */
                u64SrcPhyAddr = pstStreamBuf->u64PhyAddr[j] +
                                ((pstStream->pstPack[i].u64PhyAddr + pstStream->pstPack[i].u32Offset) -
                                (pstStreamBuf->u64PhyAddr[j] + pstStreamBuf->u64BufSize[j]));


                copySize = pstStream->pstPack[i].u32Len - pstStream->pstPack[i].u32Offset;
                if (copySize > remainBufSize) {
                    LOGE("copySize(%d) more than remainBufSize(%d) failed\n", copySize, remainBufSize);
                    return HI_FAILURE;
                }
                memcpy(pDataBuf + offset, (void *)(HI_UL)u64SrcPhyAddr, copySize);
                offset += copySize;
                remainBufSize -= copySize;
            }
            else
            {
                /* physical address retrace in data segment */
                u32Left = (pstStreamBuf->u64PhyAddr[j] + pstStreamBuf->u64BufSize[j]) - pstStream->pstPack[i].u64PhyAddr;

                copySize = u32Left - pstStream->pstPack[i].u32Offset;
                if (copySize > remainBufSize) {
                    LOGE("copySize(%d) more than remainBufSize(%d) failed\n", copySize, remainBufSize);
                    return HI_FAILURE;
                }
                memcpy(pDataBuf + offset, (void *)(HI_UL)(pstStream->pstPack[i].u64PhyAddr + pstStream->pstPack[i].u32Offset), copySize);
                offset += copySize;
                remainBufSize -= copySize;

                copySize = pstStream->pstPack[i].u32Len - u32Left;
                if (copySize > remainBufSize) {
                    LOGE("copySize(%d) more than remainBufSize(%d) failed\n", copySize, remainBufSize);
                    return HI_FAILURE;
                }
                memcpy(pDataBuf + offset, (void *)(HI_UL)pstStreamBuf->u64PhyAddr[j], copySize);
                offset += copySize;
                remainBufSize -= copySize;
            }
        }
        else
        {
            /* physical address retrace does not happen */
            copySize = pstStream->pstPack[i].u32Len - pstStream->pstPack[i].u32Offset;
            if (copySize > remainBufSize) {
                LOGE("copySize(%d) more than remainBufSize(%d) failed\n", copySize, remainBufSize);
                return HI_FAILURE;
            }
            memcpy(pDataBuf + offset, (void *)(HI_UL)(pstStream->pstPack[i].u64PhyAddr + pstStream->pstPack[i].u32Offset), copySize);
            offset += copySize;
            remainBufSize -= copySize;
        }
    }


    *pOutSize = offset;
    
    return HI_SUCCESS;
}


HI_S32 HalVideoGetSnapPic(HI_HANDLE hVEncHdl, unsigned char *pDataBuf, int dataMaxSize, int *pOutSize)
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

    if (pDataBuf == NULL || dataMaxSize <= 0 || pOutSize == NULL) {
        LOGE("params is null\n");
        return -1;
    }

    struct timeval TimeoutVal;
    fd_set read_fds;
    HI_S32 s32VencFd;
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream;
    HI_S32 s32Ret;
    HI_S32 SnapCnt = 1;
    HI_S32 VencChn = hVEncHdl;
    VENC_RECV_PIC_PARAM_S  stRecvParam;
    MPP_CHN_S stDestChn;
    MPP_CHN_S stSrcChn;
    VPSS_CHN_ATTR_S stVpssChnAttr;
    HI_U32 i;

#ifdef __HuaweiLite__
    VENC_STREAM_BUF_INFO_S  stStreamBufInfo;
#endif

    /******************************************
     step 2:  Start Recv Venc Pictures
    ******************************************/
    stRecvParam.s32RecvPicNum = SnapCnt;
    s32Ret = HI_MPI_VENC_StartRecvFrame(VencChn, &stRecvParam);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("HI_MPI_VENC_StartRecvPic faild with%#x!\n", s32Ret);
        return HI_FAILURE;
    }

    /******************************************
     step 3:  Start Recv Venc Pictures
    ******************************************/
    stDestChn.enModId  = HI_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = VencChn;
    s32Ret = HI_MPI_SYS_GetBindbyDest(&stDestChn, &stSrcChn);
    if (s32Ret == HI_SUCCESS && stSrcChn.enModId == HI_ID_VPSS)
    {
        s32Ret = HI_MPI_VPSS_GetChnAttr(stSrcChn.s32DevId, stSrcChn.s32ChnId, &stVpssChnAttr);
        if (s32Ret == HI_SUCCESS && stVpssChnAttr.enCompressMode != COMPRESS_MODE_NONE)
        {
            s32Ret = HI_MPI_VPSS_TriggerSnapFrame(stSrcChn.s32DevId, stSrcChn.s32ChnId, SnapCnt);
            if (s32Ret != HI_SUCCESS)
            {
                LOGE("call HI_MPI_VPSS_TriggerSnapFrame Grp = %d, ChanId = %d, SnapCnt = %d return failed(0x%x)!\n",
                    stSrcChn.s32DevId, stSrcChn.s32ChnId, SnapCnt, s32Ret);

                return HI_FAILURE;
            }
        }
    }

    /******************************************
     step 4:  recv picture
    ******************************************/
    s32VencFd = HI_MPI_VENC_GetFd(VencChn);
    if (s32VencFd < 0)
    {
        LOGE("HI_MPI_VENC_GetFd faild with%#x!\n", s32VencFd);
        return HI_FAILURE;
    }

    for(i=0; i< SnapCnt; i++)
    {
        FD_ZERO(&read_fds);
        FD_SET(s32VencFd, &read_fds);
        TimeoutVal.tv_sec  = 10;
        TimeoutVal.tv_usec = 0;
        s32Ret = select(s32VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal);
        if (s32Ret < 0)
        {
            LOGE("snap select failed!\n");
            return HI_FAILURE;
        }
        else if (0 == s32Ret)
        {
            LOGE("snap time out!\n");
            return HI_FAILURE;
        }
        else
        {
            if (FD_ISSET(s32VencFd, &read_fds))
            {
                s32Ret = HI_MPI_VENC_QueryStatus(VencChn, &stStat);
                if (s32Ret != HI_SUCCESS)
                {
                    LOGE("HI_MPI_VENC_QueryStatus failed with %#x!\n", s32Ret);
                    return HI_FAILURE;
                }
                /*******************************************************
                suggest to check both u32CurPacks and u32LeftStreamFrames at the same time,for example:
                 if(0 == stStat.u32CurPacks || 0 == stStat.u32LeftStreamFrames)
                 {                SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                    return HI_SUCCESS;
                 }
                 *******************************************************/
                if (0 == stStat.u32CurPacks)
                {
                    LOGE("NOTE: Current  frame is NULL!\n");
                    return HI_SUCCESS;
                }
                stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
                if (NULL == stStream.pstPack)
                {
                    LOGE("malloc memory failed!\n");
                    return HI_FAILURE;
                }
                stStream.u32PackCount = stStat.u32CurPacks;
                s32Ret = HI_MPI_VENC_GetStream(VencChn, &stStream, -1);
                if (HI_SUCCESS != s32Ret)
                {
                    LOGE("HI_MPI_VENC_GetStream failed with %#x!\n", s32Ret);

                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    return HI_FAILURE;
                }
#ifndef __HuaweiLite__
                s32Ret = SAMPLE_COMM_VENC_SaveStream(pFile, &stStream);
                if (HI_SUCCESS != s32Ret)
                {
                    LOGE("save snap picture failed!\n");

                    free(stStream.pstPack);
                    stStream.pstPack = NULL;

                    fclose(pFile);
                    return HI_FAILURE;
                }

#else
                s32Ret = HI_MPI_VENC_GetStreamBufInfo (VencChn, &stStreamBufInfo);
                if (HI_SUCCESS != s32Ret)
                {
                    LOGE("HI_MPI_VENC_GetStreamBufInfo failed with %#x!\n", s32Ret);

                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    return HI_FAILURE;
                }

                s32Ret = copy_jpg_data(pDataBuf, dataMaxSize, pOutSize, &stStreamBufInfo, &stStream);
                if (HI_SUCCESS != s32Ret)
                {
                    LOGE("save snap picture failed!\n");

                    free(stStream.pstPack);
                    stStream.pstPack = NULL;

                    return HI_FAILURE;
                }
#endif
                s32Ret = HI_MPI_VENC_ReleaseStream(VencChn, &stStream);
                if (HI_SUCCESS != s32Ret)
                {
                    LOGE("HI_MPI_VENC_ReleaseStream failed with %#x!\n", s32Ret);

                    free(stStream.pstPack);
                    stStream.pstPack = NULL;

                    return HI_FAILURE;
                }

                free(stStream.pstPack);
                stStream.pstPack = NULL;
            }
        }
    }
    /******************************************
     step 5:  stop recv picture
    ******************************************/
    s32Ret = HI_MPI_VENC_StopRecvFrame(VencChn);
    if (s32Ret != HI_SUCCESS)
    {
        LOGE("HI_MPI_VENC_StopRecvPic failed with %#x!\n",  s32Ret);
        return HI_FAILURE;
    }
    
    return HI_SUCCESS;
}

#ifdef ENABLE_AUDIO
static HI_S32 AEncDataProc2(__attribute__((unused))HI_HANDLE hAEncHdl, HI_MW_MEDIA_AUDIO_S* pAStreamData, HI_VOID* pPrivateData)
{
    HI_Track_Source_Handle pTrackSource =  (HI_Track_Source_Handle)pPrivateData;
    HI_RTSP_DATA_S stFrame;
    stFrame.au32DataLen[0] = pAStreamData->u32Len;
    stFrame.u32Seq = 1;
    stFrame.apu8DataPtr[0] = pAStreamData->pu8Addr;
    stFrame.u32BlockCnt = 1;
    stFrame.bIsKeyFrame = HI_FALSE;

    stFrame.u64Pts = pAStreamData->u64TimeStamp;


    HI_RTSPSVR_WriteFrame(s_hRtspServerHandle,  pTrackSource, &stFrame);

}

static HI_S32 AEncDataProc(__attribute__((unused))HI_HANDLE hAEncHdl, HI_MW_MEDIA_AUDIO_S* pAStreamData, HI_VOID* pPrivateData)
{
    HI_Track_Source_Handle pTrackSource = (HI_Track_Source_Handle)pPrivateData;
    HI_REC_FRAME_DATA_S stRecFrame;
    stRecFrame.u32SliceCnt = 1;
    stRecFrame.u64TimeStamp = pAStreamData->u64TimeStamp;
    stRecFrame.apu8SliceAddr[0] = pAStreamData->pu8Addr;
    stRecFrame.au32SliceLen[0] = pAStreamData->u32Len;
    stRecFrame.bKeyFrameFlag = HI_FALSE;
    return HI_REC_WriteData(g_hRecHandle, pTrackSource, &stRecFrame);
}

HI_S32 Aenc4RtspStart(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    return HI_MW_AEnc_Start(pTrackSource->s32PrivateHandle, AEncDataProc2, pTrackSource );
}

HI_S32 AencStart(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    return HI_MW_AEnc_Start(pTrackSource->s32PrivateHandle, AEncDataProc, pTrackSource);
}

HI_S32 Aenc4RtspStop(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    HI_S32 s32Ret = HI_MW_AEnc_Stop(pTrackSource->s32PrivateHandle, AEncDataProc2);
    return s32Ret;
}

HI_S32 AencStop(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    return HI_MW_AEnc_Stop(pTrackSource->s32PrivateHandle, AEncDataProc);
}
#else
/*
HI_S32 Aenc4RtspStart(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    return HI_SUCCESS;
}

HI_S32 AencStart(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    return HI_SUCCESS;
}

HI_S32 Aenc4RtspStop(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    return HI_SUCCESS;
}

HI_S32 AencStop(HI_Track_Source_Handle pTrackSource, HI_MW_PTR pCaller)
{
    return HI_SUCCESS;
}
*/
#endif

HI_S32 GetMainVEncAttr(HI_MW_VEncAttr* pstVEncAttr)
{
    memcpy(pstVEncAttr, &s_stVEnc4MainAttr, sizeof(HI_MW_VEncAttr));
    return HI_SUCCESS;
}

HI_S32 GetSlaveVEncAttr(HI_MW_VEncAttr* pstVEncAttr)
{
    memcpy(pstVEncAttr, &s_stVEnc4SlaveAttr, sizeof(HI_MW_VEncAttr));
    return HI_SUCCESS;
}

HI_S32 GetLiveVEncAttr(HI_MW_VEncAttr* pstVEncAttr)
{
    memcpy(pstVEncAttr, &s_stVEnc4SlaveAttr, sizeof(HI_MW_VEncAttr));
    return HI_SUCCESS;
}

HI_S32 HalVideoInit()
{
#ifdef MINI_APP
    return HI_SUCCESS;
#endif /* MINI_APP */

    int width = 0;
    int height = 0;
    int bitrate = 0;
    
    DevConfigGetVideoResolution(&width, &height, &bitrate);
    if (width != 0 && height != 0 && bitrate != 0)
    {
        s_astMediaAttr[0].pstVEncAttr->WIDTH = width;
        s_astMediaAttr[0].pstVEncAttr->HEIGHT = height;
        s_astMediaAttr[0].pstVEncAttr->BUFSIZE = width * height * 2;
        s_astMediaAttr[0].pstVEncAttr->BITRATE = bitrate;
    }
    
    //return HI_MW_Media_Init(&s_stSensorAttr, &s_stVCapAttr, s_astMediaAttr, 3, 0, 0);

    return HI_MW_Media_Init(&s_stSensorAttr, &s_stVCapAttr, s_astMediaAttr, 2, 0, 0);
}

HI_S32 HalVideoDeInit()
{
#ifdef MINI_APP
        return HI_SUCCESS;
#endif /* MINI_APP */

    //return HI_MW_Media_DeInit(&s_stSensorAttr, &s_stVCapAttr, s_astMediaAttr, 3, 0, 0);
    return HI_MW_Media_DeInit(&s_stSensorAttr, &s_stVCapAttr, s_astMediaAttr, 2, 0, 0);
}

HI_S32 GetAEncAttr(HI_HANDLE* pstAEncAttr)
{
    *pstAEncAttr = 0;
    return HI_SUCCESS;
}



